home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / src / binutils.252 / gas / subsegs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-26  |  13.8 KB  |  541 lines

  1. /* subsegs.c - subsegments -
  2.    Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
  3.    Free Software Foundation, Inc.
  4.  
  5.    This file is part of GAS, the GNU Assembler.
  6.  
  7.    GAS is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2, or (at your option)
  10.    any later version.
  11.  
  12.    GAS is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with GAS; see the file COPYING.  If not, write to
  19.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /*
  22.  * Segments & sub-segments.
  23.  */
  24.  
  25. #include "as.h"
  26.  
  27. #include "subsegs.h"
  28. #include "obstack.h"
  29.  
  30. frchainS *frchain_root, *frchain_now;
  31.  
  32. #ifndef BFD_ASSEMBLER
  33. #ifdef MANY_SEGMENTS
  34. segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
  35.  
  36. #else
  37. /* Commented in "subsegs.h". */
  38. frchainS *data0_frchainP, *bss0_frchainP;
  39.  
  40. #endif /* MANY_SEGMENTS */
  41. char *const seg_name[] =
  42. {
  43.   "absolute",
  44. #ifdef MANY_SEGMENTS
  45.   "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
  46. #else
  47.   "text",
  48.   "data",
  49.   "bss",
  50. #endif /* MANY_SEGMENTS */
  51.   "unknown",
  52.   "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
  53.   "expr",
  54.   "debug",
  55.   "transfert vector preload",
  56.   "transfert vector postload",
  57.   "register",
  58.   "",
  59. };                /* Used by error reporters, dumpers etc. */
  60. #else /* BFD_ASSEMBLER */
  61.  
  62. /* Gas segment information for bfd_abs_section_ptr and
  63.    bfd_und_section_ptr.  */
  64. static segment_info_type *abs_seg_info;
  65. static segment_info_type *und_seg_info;
  66.  
  67. #endif /* BFD_ASSEMBLER */
  68.  
  69. static void subseg_set_rest PARAMS ((segT, subsegT));
  70.  
  71. void
  72. subsegs_begin ()
  73. {
  74.   /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
  75. #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
  76.   know (SEG_ABSOLUTE == 0);
  77.   know (SEG_TEXT == 1);
  78.   know (SEG_DATA == 2);
  79.   know (SEG_BSS == 3);
  80.   know (SEG_UNKNOWN == 4);
  81.   know (SEG_GOOF == 5);
  82.   know (SEG_EXPR == 6);
  83.   know (SEG_DEBUG == 7);
  84.   know (SEG_NTV == 8);
  85.   know (SEG_PTV == 9);
  86.   know (SEG_REGISTER == 10);
  87.   know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
  88. #endif
  89.  
  90.   obstack_begin (&frags, 5000);
  91.   frchain_root = NULL;
  92.   frchain_now = NULL;        /* Warn new_subseg() that we are booting. */
  93.   /* Fake up 1st frag.  It won't be used=> is ok if obstack...
  94.      pads the end of it for alignment. */
  95.   frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
  96.   memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
  97.  
  98. #ifndef BFD_ASSEMBLER
  99.   /* This 1st frag will not be in any frchain.
  100.      We simply give subseg_new somewhere to scribble. */
  101.   now_subseg = 42;        /* Lie for 1st call to subseg_new. */
  102. #ifdef MANY_SEGMENTS
  103.   {
  104.     int i;
  105.     for (i = SEG_E0; i < SEG_UNKNOWN; i++)
  106.       {
  107.     subseg_set (i, 0);
  108.     segment_info[i].frchainP = frchain_now;
  109.       }
  110.   }
  111. #else
  112.   subseg_set (SEG_DATA, 0);    /* .data 0 */
  113.   data0_frchainP = frchain_now;
  114.  
  115.   subseg_set (SEG_BSS, 0);
  116.   bss0_frchainP = frchain_now;
  117.  
  118. #endif /* ! MANY_SEGMENTS */
  119. #endif /* ! BFD_ASSEMBLER */
  120.  
  121. }
  122.  
  123. /*
  124.  *            subseg_change()
  125.  *
  126.  * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
  127.  * subsegment. If we are already in the correct subsegment, change nothing.
  128.  * This is used eg as a worker for subseg_set [which does make a new frag_now]
  129.  * and for changing segments after we have read the source. We construct eg
  130.  * fixSs even after the source file is read, so we do have to keep the
  131.  * segment context correct.
  132.  */
  133. void
  134. subseg_change (seg, subseg)
  135.      register segT seg;
  136.      register int subseg;
  137. {
  138.   now_seg = seg;
  139.   now_subseg = subseg;
  140.  
  141. #ifdef BFD_ASSEMBLER
  142.   {
  143.     segment_info_type *seginfo;
  144.     seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
  145.     if (! seginfo)
  146.       {
  147.     seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
  148.     memset ((PTR) seginfo, 0, sizeof (*seginfo));
  149.     seginfo->fix_root = NULL;
  150.     seginfo->fix_tail = NULL;
  151.     seginfo->bfd_section = seg;
  152.     seginfo->sym = 0;
  153.     if (seg == bfd_abs_section_ptr)
  154.       abs_seg_info = seginfo;
  155.     else if (seg == bfd_und_section_ptr)
  156.       und_seg_info = seginfo;
  157.     else
  158.       bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
  159.       }
  160.   }
  161. #else
  162. #ifdef MANY_SEGMENTS
  163.   seg_fix_rootP = &segment_info[seg].fix_root;
  164.   seg_fix_tailP = &segment_info[seg].fix_tail;
  165. #else
  166.   if (seg == SEG_DATA)
  167.     {
  168.       seg_fix_rootP = &data_fix_root;
  169.       seg_fix_tailP = &data_fix_tail;
  170.     }
  171.   else if (seg == SEG_TEXT)
  172.     {
  173.       seg_fix_rootP = &text_fix_root;
  174.       seg_fix_tailP = &text_fix_tail;
  175.     }
  176.   else
  177.     {
  178.       know (seg == SEG_BSS);
  179.       seg_fix_rootP = &bss_fix_root;
  180.       seg_fix_tailP = &bss_fix_tail;
  181.     }
  182.  
  183. #endif
  184. #endif
  185. }
  186.  
  187. static void
  188. subseg_set_rest (seg, subseg)
  189.      segT seg;
  190.      subsegT subseg;
  191. {
  192.   long tmp;            /* JF for obstack alignment hacking */
  193.   register frchainS *frcP;    /* crawl frchain chain */
  194.   register frchainS **lastPP;    /* address of last pointer */
  195.   frchainS *newP;        /* address of new frchain */
  196.   register fragS *former_last_fragP;
  197.   register fragS *new_fragP;
  198.  
  199.   if (frag_now)        /* If not bootstrapping. */
  200.     {
  201.       frag_now->fr_fix = (char*) obstack_next_free (&frags) - frag_now->fr_literal;
  202.       frag_wane (frag_now);    /* Close off any frag in old subseg. */
  203.     }
  204.   /*
  205.    * It would be nice to keep an obstack for each subsegment, if we swap
  206.    * subsegments a lot. Hence we would have much fewer frag_wanes().
  207.    */
  208.   {
  209.     obstack_finish (&frags);
  210.     /*
  211.      * If we don't do the above, the next object we put on obstack frags
  212.      * will appear to start at the fr_literal of the current frag.
  213.      * Also, above ensures that the next object will begin on a
  214.      * address that is aligned correctly for the engine that runs
  215.      * this program.
  216.      */
  217.   }
  218.   subseg_change (seg, (int) subseg);
  219.   /*
  220.    * Attempt to find or make a frchain for that sub seg.
  221.    * Crawl along chain of frchainSs, begins @ frchain_root.
  222.    * If we need to make a frchainS, link it into correct
  223.    * position of chain rooted in frchain_root.
  224.    */
  225.   for (frcP = *(lastPP = &frchain_root);
  226.        frcP && frcP->frch_seg <= seg;
  227.        frcP = *(lastPP = &frcP->frch_next))
  228.     {
  229.       if (frcP->frch_seg == seg
  230.       && frcP->frch_subseg >= subseg)
  231.     {
  232.       break;
  233.     }
  234.     }
  235.   /*
  236.    * frcP:        Address of the 1st frchainS in correct segment with
  237.    *        frch_subseg >= subseg.
  238.    *        We want to either use this frchainS, or we want
  239.    *        to insert a new frchainS just before it.
  240.    *
  241.    *        If frcP==NULL, then we are at the end of the chain
  242.    *        of frchainS-s. A NULL frcP means we fell off the end
  243.    *        of the chain looking for a
  244.    *        frch_subseg >= subseg, so we
  245.    *        must make a new frchainS.
  246.    *
  247.    *        If we ever maintain a pointer to
  248.    *        the last frchainS in the chain, we change that pointer
  249.    *        ONLY when frcP==NULL.
  250.    *
  251.    * lastPP:    Address of the pointer with value frcP;
  252.    *        Never NULL.
  253.    *        May point to frchain_root.
  254.    *
  255.    */
  256.   if (!frcP
  257.       || (frcP->frch_seg > seg
  258.       || frcP->frch_subseg > subseg))    /* Kinky logic only works with 2 segments. */
  259.     {
  260.       /*
  261.        * This should be the only code that creates a frchainS.
  262.        */
  263.       newP = (frchainS *) obstack_alloc (&frags, sizeof (frchainS));
  264.       memset (newP, 0, sizeof (frchainS));
  265.       /* This begines on a good boundary because a obstack_done()
  266.      preceeded it.  It implies an obstack_done(), so we expect
  267.      the next object allocated to begin on a correct boundary. */
  268.       *lastPP = newP;
  269.       newP->frch_next = frcP;    /* perhaps NULL */
  270.       (frcP = newP)->frch_subseg = subseg;
  271.       newP->frch_seg = seg;
  272.       newP->frch_last = NULL;
  273. #ifdef BFD_ASSEMBLER
  274.       newP->fix_root = NULL;
  275.       newP->fix_tail = NULL;
  276. #endif
  277.     }
  278.   /*
  279.    * Here with frcP ->ing to the frchainS for subseg.
  280.    */
  281.   frchain_now = frcP;
  282.   /*
  283.    * Make a fresh frag for the subsegment.
  284.    */
  285.   /* We expect this to happen on a correct boundary since it was
  286.      proceeded by a obstack_done(). */
  287.   tmp = obstack_alignment_mask (&frags);    /* JF disable alignment */
  288.   obstack_alignment_mask (&frags) = 0;
  289.   frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
  290.   memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
  291.   obstack_alignment_mask (&frags) = tmp;
  292.   /* But we want any more chars to come immediately after the
  293.      structure we just made. */
  294.   new_fragP = frag_now;
  295.   new_fragP->fr_next = NULL;
  296.   /*
  297.    * Append new frag to current frchain.
  298.    */
  299.   former_last_fragP = frcP->frch_last;
  300.   if (former_last_fragP)
  301.     {
  302.       know (former_last_fragP->fr_next == NULL);
  303.       know (frchain_now->frch_root);
  304.       former_last_fragP->fr_next = new_fragP;
  305.     }
  306.   else
  307.     {
  308.       frcP->frch_root = new_fragP;
  309.     }
  310.   frcP->frch_last = new_fragP;
  311. }
  312.  
  313. /*
  314.  *            subseg_set(segT, subsegT)
  315.  *
  316.  * If you attempt to change to the current subsegment, nothing happens.
  317.  *
  318.  * In:    segT, subsegT code for new subsegment.
  319.  *    frag_now -> incomplete frag for current subsegment.
  320.  *    If frag_now==NULL, then there is no old, incomplete frag, so
  321.  *    the old frag is not closed off.
  322.  *
  323.  * Out:    now_subseg, now_seg updated.
  324.  *    Frchain_now points to the (possibly new) struct frchain for this
  325.  *    sub-segment.
  326.  *    Frchain_root updated if needed.
  327.  */
  328.  
  329. #ifndef BFD_ASSEMBLER
  330.  
  331. segT
  332. subseg_new (segname, subseg)
  333.      const char *segname;
  334.      subsegT subseg;
  335. {
  336.   int i;
  337.  
  338.   for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
  339.     {
  340.       const char *s;
  341.  
  342.       s = segment_name ((segT) i);
  343.       if (strcmp (segname, s) == 0
  344.       || (segname[0] == '.'
  345.           && strcmp (segname + 1, s) == 0))
  346.     {
  347.       subseg_set ((segT) i, subseg);
  348.       return (segT) i;
  349.     }
  350. #ifdef obj_segment_name
  351.       s = obj_segment_name ((segT) i);
  352.       if (strcmp (segname, s) == 0
  353.       || (segname[0] == '.'
  354.           && strcmp (segname + 1, s) == 0))
  355.     {
  356.       subseg_set ((segT) i, subseg);
  357.       return (segT) i;
  358.     }
  359. #endif
  360.     }
  361.  
  362. #ifdef obj_add_segment
  363.   {
  364.     segT new_seg;
  365.     new_seg = obj_add_segment (segname);
  366.     subseg_set (new_seg, subseg);
  367.     return new_seg;
  368.   }
  369. #else
  370.   as_bad ("Attempt to switch to nonexistent segment \"%s\"", segname);
  371.   return now_seg;
  372. #endif
  373. }
  374.  
  375. void
  376. subseg_set (seg, subseg)    /* begin assembly for a new sub-segment */
  377.      register segT seg;        /* SEG_DATA or SEG_TEXT */
  378.      register subsegT subseg;
  379. {
  380. #ifndef MANY_SEGMENTS
  381.   know (seg == SEG_DATA || seg == SEG_TEXT || seg == SEG_BSS);
  382. #endif
  383.  
  384.   if (seg != now_seg || subseg != now_subseg)
  385.     {                /* we just changed sub-segments */
  386.       subseg_set_rest (seg, subseg);
  387.     }
  388. }
  389.  
  390. #else /* BFD_ASSEMBLER */
  391.  
  392. segT
  393. subseg_get (segname, force_new)
  394.      const char *segname;
  395.      int force_new;
  396. {
  397.   segT secptr;
  398.   segment_info_type *seginfo;
  399.   const char *now_seg_name = (now_seg
  400.                   ? bfd_get_section_name (stdoutput, now_seg)
  401.                   : 0);
  402.  
  403.   if (!force_new
  404.       && now_seg_name
  405.       && (now_seg_name == segname
  406.       || !strcmp (now_seg_name, segname)))
  407.     return now_seg;
  408.  
  409.   if (!force_new)
  410.     secptr = bfd_make_section_old_way (stdoutput, segname);
  411.   else
  412.     secptr = bfd_make_section_anyway (stdoutput, segname);
  413.  
  414.   seginfo = seg_info (secptr);
  415.   if (! seginfo)
  416.     {
  417.       /* Check whether output_section is set first because secptr may
  418.          be bfd_abs_section_ptr.  */
  419.       if (secptr->output_section != secptr)
  420.     secptr->output_section = secptr;
  421.       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
  422.       memset ((PTR) seginfo, 0, sizeof (*seginfo));
  423.       seginfo->fix_root = NULL;
  424.       seginfo->fix_tail = NULL;
  425.       seginfo->bfd_section = secptr;
  426.       if (secptr == bfd_abs_section_ptr)
  427.     abs_seg_info = seginfo;
  428.       else if (secptr == bfd_und_section_ptr)
  429.     und_seg_info = seginfo;
  430.       else
  431.     bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
  432.       seginfo->frchainP = NULL;
  433.       seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
  434.       seginfo->sym = NULL;
  435.       seginfo->dot = NULL;
  436.     }
  437.   return secptr;
  438. }
  439.  
  440. segT
  441. subseg_new (segname, subseg)
  442.      const char *segname;
  443.      subsegT subseg;
  444. {
  445.   segT secptr;
  446.   segment_info_type *seginfo;
  447.  
  448.   secptr = subseg_get (segname, 0);
  449.   subseg_set_rest (secptr, subseg);
  450.   seginfo = seg_info (secptr);
  451.   if (! seginfo->frchainP)
  452.     seginfo->frchainP = frchain_now;
  453.   return secptr;
  454. }
  455.  
  456. /* Like subseg_new, except a new section is always created, even if
  457.    a section with that name already exists.  */
  458. segT
  459. subseg_force_new (segname, subseg)
  460.      const char *segname;
  461.      subsegT subseg;
  462. {
  463.   segT secptr;
  464.   segment_info_type *seginfo;
  465.  
  466.   secptr = subseg_get (segname, 1);
  467.   subseg_set_rest (secptr, subseg);
  468.   seginfo = seg_info (secptr);
  469.   if (! seginfo->frchainP)
  470.     seginfo->frchainP = frchain_now;
  471.   return secptr;
  472. }
  473.  
  474. void
  475. subseg_set (secptr, subseg)
  476.      segT secptr;
  477.      subsegT subseg;
  478. {
  479.   if (! (secptr == now_seg && subseg == now_subseg))
  480.     subseg_set_rest (secptr, subseg);
  481. }
  482.  
  483. #ifndef obj_sec_sym_ok_for_reloc
  484. #define obj_sec_sym_ok_for_reloc(SEC)    0
  485. #endif
  486.  
  487. /* Get the gas information we are storing for a section.  */
  488.  
  489. segment_info_type *
  490. seg_info (sec)
  491.      segT sec;
  492. {
  493.   if (sec == bfd_abs_section_ptr)
  494.     return abs_seg_info;
  495.   else if (sec == bfd_und_section_ptr)
  496.     return und_seg_info;
  497.   else
  498.     return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
  499. }
  500.  
  501. symbolS *
  502. section_symbol (sec)
  503.      segT sec;
  504. {
  505.   segment_info_type *seginfo = seg_info (sec);
  506.   symbolS *s;
  507.  
  508.   if (seginfo == 0)
  509.     abort ();
  510.   if (seginfo->sym)
  511.     return seginfo->sym;
  512.   s = symbol_find (sec->name);
  513.   if (!s)
  514.     {
  515. #ifndef EMIT_SECTION_SYMBOLS
  516. #define EMIT_SECTION_SYMBOLS 1
  517. #endif
  518.  
  519.       if (! EMIT_SECTION_SYMBOLS
  520. #ifdef BFD_ASSEMBLER
  521.       && symbol_table_frozen
  522. #endif
  523.       )
  524.     /* Here we know it won't be going into the symbol table.  */
  525.     s = symbol_create (sec->name, sec, 0, &zero_address_frag);
  526.       else
  527.     s = symbol_new (sec->name, sec, 0, &zero_address_frag);
  528.       S_CLEAR_EXTERNAL (s);
  529.  
  530.       /* Use the BFD section symbol, if possible.  */
  531.       if (obj_sec_sym_ok_for_reloc (sec))
  532.     s->bsym = sec->symbol;
  533.     }
  534.   seginfo->sym = s;
  535.   return s;
  536. }
  537.  
  538. #endif /* BFD_ASSEMBLER */
  539.  
  540. /* end of subsegs.c */
  541.